﻿using System.ComponentModel;
using System.ServiceModel.DomainServices.Client;
using System.Windows.Data;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Windows.Data.DomainServices;
using WebHost;


namespace SilverlightShowWCFRIAColl.ViewModels
{
    public class DomainCollectionViewViewModel : ViewModelBase
    { 
        
        private BookDomainContext _context;
        /// <summary>
        /// The Context property
        /// </summary>
        public BookDomainContext Context
        {
            get
            {
                if (_context == null)
                {
                    _context = new BookDomainContext();
                }
                return _context;
            }
            set
            {
                _context = value;
                RaisePropertyChanged("Context");
            }
        }



        public RelayCommand AddBook
        {
            get;
            private set;
        }

        public RelayCommand AddFilter
        {
            get;
            private set;
        }

        public RelayCommand DeleteBook
        {
            get;
            private set;
        }



        public RelayCommand AddSort
        {
            get;
            private set;
        }


        public RelayCommand AddGrouping
        {
            get;
            private set;
        }

        public RelayCommand Refresh
        {
            get;
            private set;
        }


        public DomainCollectionView<Book> Books
        {
            get { 
                return this.view; 
            }
        }

        private EntityQuery<Book> query;
        private DomainCollectionView<Book> view;
        private DomainCollectionViewLoader<Book> loader;
        private EntityList<Book> source;




        public DomainCollectionViewViewModel()
        {
            InstantiateCommands();

            this.query = Context.GetOrderedBooksQuery();
            this.query.IncludeTotalCount = true;
            this.source = new EntityList<Book>(Context.Books);
            this.loader = new DomainCollectionViewLoader<Book>(
              this.OnLoadBooks,
              this.OnLoadBooksCompleted);

            this.view = new DomainCollectionView<Book>(loader, source);

            using (this.view.DeferRefresh())
            {
                this.view.PageSize = 5;
                this.view.MoveToFirstPage();
            }

        }

        private LoadOperation<Book> OnLoadBooks()
        {
            return this.Context.Load(this.query.SortPageAndCount(this.view));
        }

        private void OnLoadBooksCompleted(LoadOperation<Book> op)
        {
            if (op.HasError)
            {
                op.MarkErrorAsHandled();
            }
            else if (!op.IsCanceled)
            {
                this.source.Source = op.Entities;
                if (op.TotalEntityCount != -1)
                {
                    this.Books.SetTotalItemCount(op.TotalEntityCount);
                }
            }
        }


        private void InstantiateCommands()
        {
            AddBook = new RelayCommand(() =>
            {
                // you can add books like this, but DCV is server side oriented: to get correct 
                // behaviour, you should add it to the Context and submit the changes, after which
                // the next query will fetch the book you just added.
                Book book = Books.AddNew() as Book;
                book.Author = "Kevin Dockx";
                book.ASIN = "123456";
                book.Title = "Silverlight for dummies";
            });

            DeleteBook = new RelayCommand(() =>
            {
                // deleting an item can be done like this, but should be done directly on the context 
                // & submitted to the server
                Books.RemoveAt(0);
            });

            AddSort = new RelayCommand(() =>
            {
                Books.SortDescriptions.Add(new SortDescription("Title", ListSortDirection.Ascending));
                Books.Refresh();
            });

            AddGrouping = new RelayCommand(() =>
            {
                Books.GroupDescriptions.Add(new PropertyGroupDescription("Author"));
                Books.Refresh();
            });

            AddFilter = new RelayCommand(() =>
            {
                // filters in DCV should be done by adding a Where clause to the query, as DCV is mainly used for
                // server side logic

                this.query = Context.GetOrderedBooksQuery().Where(b => b.Title.Contains("Silverlight"));
                this.view.MoveToFirstPage();

            });

            Refresh = new RelayCommand(() =>
            {
                Books.Refresh();
            });
        }


    }
}
